if (!window.Mold) var Mold = (function () {

    const FRONT = 0, RIGHT = 1, TOP = 2, letter = "0123456789ABCDEF";

    var order = 8,                   // 立方阶数，默认为8，可由init函数传入
        tc = $ ('#top-container'),   // 3 个视图的jQuery容器
        lc = $ ('#left-container'),
        fc = $ ('#front-container'),
        result = $('.result'),       // 结果显示区域
        top = [],                    // 3 个视图的jQuery数组
        right = [],
        front = [],
        bits = [],                   // 3维数组，对应立方体的每个点
        numbers = [],                // xy平面的每一行的8位组成一个字节
        d = $('#debug-panel');

    function createTable (id, index) {
        var table = $ ('<table class="side"/>').attr ({'data-index':index, 'data-id':id}), i, j, tr;
        $ ('<caption align="bottom"/>').text (index).appendTo (table);
        for (i = 0; i < order; i++) {
            tr = $ ('<tr />').appendTo (table);
            for (j = 0; j < order; j++) {
                $ ('<td class="node"/>').attr ({'data-r':i, 'data-c':j}).on ('click', onCellClick).appendTo (tr);
            }
        }
        return table;
    }

    function onCellClick () {
        var self = $ (this),
            table = self.closest ('table'),
            index = parseInt (table.attr ('data-index'), 10),
            side = parseInt (table.attr ('data-id'), 10),
            r = parseInt (self.attr ('data-r'), 10),
            c = parseInt (self.attr ('data-c'), 10),
            x, y, z;

        switch (side) {
            case FRONT : // front
                x = c;
                y = order - r - 1;
                z = index;
                break;
            case RIGHT :
                x = order - index - 1;
                y = order - r - 1;
                z = c;
                break;
            case TOP :
                x = c;
                y = order - index - 1;
                z = order - r - 1;
                break;
            default :
                break;
        }

        var s = '(x,y,z) = (' + x + ',' + y + ',' + z + ')';
        console.log (s);
        d.text (s);

        updateUI (x, y, z);
    }

    function updateUI (x, y, z) {
        var table, row, cell, n = bits [x][y][z];
        if (n == 1) {
            n = 0;
        } else {
            n = 1;
        }
        bits [x][y][z] = n;
        // update front
        // for front-view:
        // row: order - y
        // column: x
        // slice: z
        {
            table = front [z];
            row = table[0].rows [order - y - 1];
            cell = row.cells [x];
            if (n) {
                $(cell).addClass('node-on');
            } else {
                $(cell).removeClass('node-on');
            }
        }

        // for right-view
        // slice: order - x - 1
        // row: order - y - 1
        // column: z
        {
            table = right [order - x - 1];
            row = table[0].rows [order - y - 1];
            cell = row.cells [z];
            if (n) {
                $(cell).addClass('node-on');
            } else {
                $(cell).removeClass('node-on');
            }
        }

        // for top-view
        // slice: order - y - 1
        // row: order - z - 1
        // column: x
        {
            table = top [order - y - 1];
            row = table[0].rows [order - z - 1];
            cell = row.cells [x];
            if (n) {
                $(cell).addClass('node-on');
            } else {
                $(cell).removeClass('node-on');
            }
        }

        updateNumber ();
    }

    function setBit (n, b) {
        return n | (1 << (order - b - 1));
    }

    function resetBit (n, b) {
        return n & (~(1 << (order - b - 1)));
    }

    function i2h (n) {
        var h = (n >> 4) & 0x0f, l = n & 0x0f;
        return '0x' + letter [h] + letter [l];
    }

    function updateNumber () {
        var n, x, y, z, bit;
        for (z = 0; z < order; z ++) {
            for (y = 0; y < order; y ++) {
                n = 0;
                for (x = 0; x < order; x ++) {
                    bit = bits [x][y][z];
                    if (bit) {
                        n = setBit (n, x);
                    } else {
                        n = resetBit (n, x);
                    }
                }
                numbers [z][order - y - 1] = n;
            }
        }

        showNumber ();
    }

    function showNumber () {
        var i, j, n, cell;
        result.empty ();
        for (i = 0; i < order; i ++) {
            cell = $('<ul class="result-cell"/>').appendTo (result);
            for (j = 0; j < order; j ++) {
                n = numbers [i][j];
                $('<li/>').text (i2h (n)).appendTo (cell);
            }
        }
    }

    return {
        init: function (options) {
            var n, i, j, k;
            if ('order' in options) {
                n = parseInt (options ['order']);
                if (n) {
                    order = n;
                }
            }

            // 初始化数据，全填零
            for (i = 0; i < order; i ++) {
                top   [i] = createTable (TOP,   i).appendTo (tc);
                right [i] = createTable (RIGHT, i).appendTo (lc);
                front [i] = createTable (FRONT, i).appendTo (fc);

                bits [i] = [];
                for (j = 0; j < order; j ++) {
                    bits [i][j] = [];
                    for (k = 0; k < order; k ++) {
                        bits [i][j][k] = 0;
                    }
                }
            }

            for (i = 0; i < order; i ++) {
                numbers [i] = [];
                for (j = 0; j < order; j ++) {
                    numbers [i][j] = 0;
                }
            }
        }
    };
}) ();